#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/7/27
# @Author  : YunZhen
# @File    : scanner.py
# @Software: PyCharm

"""
目录文件扫描器
"""
import os
import re
from pathlib import Path
from loguru import logger
from fuzzywuzzy import fuzz
from typing import List, Union, Tuple, Dict, Set


class FileScanner:
    """扫描目录中指点的文件"""

    @classmethod
    def scan_directory(
            cls,
            root: Union[Path, str],
            f_suffix: Union[Tuple, List, Set],
            /,
            max_depth: int = 3,
            recursive: bool = True,
            is_dict: bool = True,
            is_path: bool = False
    ) -> Union[List, Dict]:
        """
        扫描自定类型的文件
        :param root: 根目录路径
        :param f_suffix:  扫描文件的类型
        :param max_depth: 最大递归深度
        :param recursive: 是否递归扫描子目录
        :param is_dict: 返回的数据结构，True是dict {filename: path};False:list
        :param is_path: 返回文件路径是Path对象还是路径字符串
        :return:
        """
        found_files_list = []
        found_files_dict = {}
        # 遍历目录
        for current_dir, _, files in os.walk(root):
            current_path = Path(current_dir)
            depth = len(current_path.relative_to(root).parts)
            # 检查深度限制
            if recursive and depth > max_depth:
                continue
            # 查找所有符合类型文件
            for f in files:
                f = Path(f)
                if f.suffix.lower() in f_suffix:
                    f_path = current_path / f
                    if is_dict:
                        found_files_dict[cls.__normalize_field_value(f_path.stem)] = f_path if is_path else str(f_path)
                    else:
                        found_files_list.append(f_path if is_path else str(f_path))
        else:
            logger.info(f"文件目录: {root} 发现 - {len(found_files_list) or len(found_files_dict)}个文件")

        return found_files_list or found_files_dict

    @classmethod
    def file_filter(cls, name: str, data: Union[Dict], pattern=None, simple=None, threshold: int = 75):
        """ 根据名称匹配字典中符合的key，返回value
        :param name: 名称
        :param data: 需要匹配的数据
        :param pattern: 正则表达式
        :param simple: 相似度匹配
        :param threshold: 相似度阈值 0 - 100
        return boolean
        """
        normalized_name = cls.__normalize_field_value(name)
        # 1. 精确匹配
        file_path = data.get(normalized_name)
        if file_path is not None:
            logger.info("{}匹配成功，文件路径: {}", name, file_path)
            return file_path

        if simple or pattern:
            # 2. 模糊匹配
            best_match = None
            highest_score = 0
            for img_name in data.keys():
                # 相识度匹配
                if simple:
                    # 计算相似度
                    score = fuzz.ratio(normalized_name, img_name)
                    # 更新最佳匹配
                    if score > highest_score and score > threshold:  # 设置阈值
                        highest_score = score
                        best_match = img_name
                    # logger.debug('{} 与 {} 进行相似配，当前已配：{}，相似度：{}', name, img_name, best_match, highest_score)
                # 正则匹配
                if pattern:
                    # logger.debug('{} 与 {} 进行正则匹配，表达式：{}', name, img_name, pattern)
                    if re.search(pattern, img_name):
                        best_match = img_name
                        break
            if best_match:
                logger.info(f"匹配成功: {name} -> {best_match}%)")
                return data[best_match]

        logger.warning('{}不存在', name)
        return

    @classmethod
    def __normalize_field_value(cls, value: str) -> str:
        """
        规范化字符串
        :param value: 原始名字
        :return: 规范化后的名字
        """
        # 转换为小写
        value = value.lower()
        # 移除特殊字符和标点
        value = re.sub(r'[^\w\s]', '', value)
        # 使用unidecode处理非ASCII字符
        # name = unidecode(name)
        # 移除多余空格
        value = re.sub(r'\s+', ' ', value).strip()
        return value


if __name__ == '__main__':
    test = r'E:\PythonProject\yun-cool-cinema\media\actors\portrait'
    sca = FileScanner()

    file = sca.scan_directory(test, ['.jpg'])
    n = '黛日出了'
    print(sca.file_filter(n, file, pattern='黛日出.*'))
